import numpy as np    
from scipy.optimize import basinhopping    
import matplotlib.pyplot as plt    
import os    
    
# 定义成本计算函数    
def calculate_cost(x, parameters):    
    x1, x2, xf, xd = x    
    p1, p2, C_assemble, C_finished, C_dismantle, C_exchange, Ct1, Ct2, n1, n2, n_finished = parameters    
        
    # 零配件检测成本    
    cost_parts = x1 * Ct1 * n1 + x2 * Ct2 * n2    
    # 装配成本    
    cost_assemble = C_assemble * n_finished    
    # 产品检测成本    
    cost_product = xf * C_finished * n_finished    
    # 成品次品率计算    
    p_assembly = (1 - x1) * p1 + (1 - x2) * p2 - (1 - x1) * (1 - x2) * p1 * p2    
    pf = 1 - (1 - p_assembly) ** 2    
    # 拆解和调换成本    
    cost_rework = xd * C_dismantle * pf * n_finished    
    cost_replace = (1 - xd) * C_exchange * pf * n_finished    
    # 总成本    
    total_cost = cost_parts + cost_assemble + cost_product + cost_rework + cost_replace    
        
    return total_cost    
    
# 封装盆地跳跃优化函数    
def optimize_cost_basinhopping(parameters, count, index, show_plot=False):    
    # 定义初始猜测和边界    
    initial_guess = [0, 0, 0, 0]    
    bounds = [(0, 1), (0, 1), (0, 1), (0, 1)]    
        
    # 创建一个列表来存储每次迭代的成本    
    cost_history = []    
        
    # 定义一个回调函数，用于在每次迭代后记录成本    
    def callback(x, f, accepted):    
        cost_history.append(f)    
        
    # 使用 basinhopping 进行优化    
    result = basinhopping(lambda x: calculate_cost(x, parameters),    
                         initial_guess, niter=500, T=2.0, stepsize=0.5,    
                         minimizer_kwargs={"bounds": bounds},    
                         callback=callback)    
        
    # 输出最优解    
    best_individual = [int(i) for i in result.x]   
    best_cost = result.fun    
    print(f"Best Individual: {best_individual} (x1, x2, xf, xd)")    
    print(f"Minimum Cost: {best_cost}")    
        
    # 绘制迭代图        
    plt.figure(figsize=(10, 6))  
    plt.plot(cost_history)  
    plt.ylabel('Cost')  
    plt.xlabel('Iteration')  
    plt.title('Cost vs. Iteration')  
    plt.grid(True)  
      
    # 确保输出文件夹存在  
    output_dir = 'test2_anneal_picture'  
    if not os.path.exists(output_dir):  
        os.makedirs(output_dir)  
      
    # 保存图片到指定文件夹  
    plt.savefig(os.path.join(output_dir, f'cost_vs_iteration{count}.png'))  
    plt.close()   
    
# 参数设置    
parameters_list = [    
    (0.1, 0.1, 6, 3, 5, 6, 2, 3, 100, 100, 80),    
    (0.2, 0.2, 6, 3, 5, 6, 2, 3, 100, 100, 80),    
    (0.1, 0.1, 6, 3, 5, 30, 2, 3, 100, 100, 80),    
    (0.2, 0.2, 6, 2, 5, 30, 1, 1, 100, 100, 80),    
    (0.1, 0.2, 6, 2, 5, 10, 8, 1, 100, 100, 80),    
    (0.05, 0.05, 6, 3, 40, 10, 2, 3, 100, 100, 80)    
]    
    
# 调用优化函数    
for index, parameters in enumerate(parameters_list, start=1):    
    optimize_cost_basinhopping(parameters, index, index, show_plot=False)
